/*
 *
 * (c) Copyright Ascensio System Limited 2010-2018
 *
 * This program is freeware. You can redistribute it and/or modify it under the terms of the GNU 
 * General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html). 
 * In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that 
 * Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
 *
 * THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
 * FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
 *
 * You can contact Ascensio System SIA by email at sales@onlyoffice.com
 *
 * The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display 
 * Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
 *
 * Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains 
 * relevant author attributions when distributing the software. If the display of the logo in its graphic 
 * form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE" 
 * in every copy of the program you distribute. 
 * Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
 *
*/


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

using ASC.Api.Attributes;
using ASC.Api.Documents;
using ASC.Api.Projects.Wrappers;
using ASC.Api.Utils;
using ASC.MessagingSystem;
using ASC.Projects.Core.Domain;
using ASC.Projects.Core.Domain.Reports;
using ASC.Projects.Engine;
using ASC.Specific;
using ASC.Web.Core.Files;
using ASC.Web.Files.Services.DocumentService;
using ASC.Web.Projects.Classes;
using ASC.Web.Studio.Utility;

namespace ASC.Api.Projects
{
    public partial class ProjectApi
    {
        [Create(@"report/create")]
        public ReportState CheckReportData(string uri)
        {
            ChechDocBuilder();

            ReportState state;

            Report.TryCreateReport(uri.Split('?')[1], out state);

            return state;
        }

        [Read(@"report/status")]
        public ReportState GetReportStatus()
        {
            ChechDocBuilder();

            return DocbuilderReportsUtility.Status(ReportOrigin.Projects);
        }

        [Read(@"report/terminate")]
        public void TerminateReport()
        {
            ChechDocBuilder();

            DocbuilderReportsUtility.Terminate(ReportOrigin.Projects);
        }

        ///<summary>
        ///Creates the project report template with the parameters specified in the request. Most of the parameters are optional and depend on the report type selected.
        ///</summary>
        ///<short>
        ///Create report template
        ///</short>
        ///<category>Report</category>         
        ///<param name="name">Report name</param>
        ///<param name="period" optional="true">Report template generation period. Can be one of the following: Day/Week/Month</param>
        ///<param name="periodItem" optional="true">Period item. Can be: weekday name (for weekly report, starting with Sunday), day of the month (for monthly report).</param>
        ///<param name="hour" optional="true">Send time (hour)</param>
        ///<param name="autoGenerated" optional="true">Automatically generated or not</param>
        ///<param name="reportType" optional="true">Report type</param>
        ///<param name="tag" optional="true">Tag</param>
        ///<param name="project" optional="true">Project</param>
        ///<param name="status" optional="true">Task status</param>       
        ///<param name="departament" optional="true">Department/Group</param>
        ///<param name="userId" optional="true">User GUID</param>
        ///<param name="reportTimeInterval" optional="true">Report time interval</param>
        ///<param name="fromDate" optional="true">Report period start date</param>
        ///<param name="toDate" optional="true">Report period end date</param>
        ///<param name="viewType" optional="true">View type: view by group or view by project</param>
        ///<param name="noResponsible" optional="true">Show or hide tasks without responsible</param>   
        ///<returns>Project report template</returns>
        [Create(@"report")]
        public ReportTemplateWrapper SaveReportTemplate(
            string name,
            string period,
            int periodItem,
            int hour,
            bool autoGenerated,
            ReportType reportType,
            int tag,
            int project,
            TaskStatus? status,
            Guid departament,
            Guid userId,
            ReportTimeInterval reportTimeInterval,
            ApiDateTime fromDate,
            ApiDateTime toDate,
            int viewType,
            bool noResponsible)
        {
            ProjectSecurity.DemandAuthentication();

            if (name == null || name.Trim().Length == 0) throw new ArgumentNullException("name");

            var filter = new TaskFilter
                {
                    TagId = tag,
                    DepartmentId = departament,
                    UserId = userId,
                    TimeInterval = reportTimeInterval,
                    FromDate = fromDate,
                    ToDate = toDate,
                    ViewType = viewType,
                    NoResponsible = noResponsible
                };

            if (project != 0)
            {
                filter.ProjectIds.Add(project);
            }

            if (status != null)
            {
                filter.TaskStatuses.Add((TaskStatus)status);
            }

            var template = new ReportTemplate(reportType) { Filter = filter };

            SaveOrUpdateTemplate(template, name, period, periodItem, hour, autoGenerated);
            MessageService.Send(Request, MessageAction.ReportTemplateCreated, MessageTarget.Create(template.Id), template.Name);

            return new ReportTemplateWrapper(template);
        }

        ///<summary>
        ///Updates the selected project report template with the parameters specified in the request
        ///</summary>
        ///<short>
        ///Update report template
        ///</short>
        ///<category>Report</category>           
        ///<param name="reportid">Report template ID</param>    
        ///<param name="name">Report name</param>
        ///<param name="period" optional="true">Report template generation period. Can be one of the following: Day/Week/Month</param>
        ///<param name="periodItem" optional="true">Period item. Can be: weekday name (for weekly report, starting with Sunday), day of the month (for monthly report).</param>
        ///<param name="hour" optional="true">Send time (hour)</param>
        ///<param name="autoGenerated" optional="true">Automatically generated or not</param>
        ///<param name="reportType" optional="true">Report type</param>
        ///<param name="tag" optional="true">Tag</param>
        ///<param name="project" optional="true">Project</param>
        ///<param name="status" optional="true">Task status</param>       
        ///<param name="departament" optional="true">Department/Group</param>
        ///<param name="userId" optional="true">User GUID</param>
        ///<param name="reportTimeInterval" optional="true">Report time interval</param>
        ///<param name="fromDate" optional="true">Report period start date</param>
        ///<param name="toDate" optional="true">Report period end date</param>
        ///<param name="viewType" optional="true">View type: view by group or view by project</param>
        ///<param name="noResponsible" optional="true">Show or hide tasks without responsible</param>   
        ///<returns>Project report template</returns>
        [Update(@"report/{reportid:[0-9]+}")]
        public ReportTemplateWrapper UpdateReportTemplate(
            int reportid,
            string name,
            string period,
            int periodItem,
            int hour,
            bool autoGenerated,
            ReportType reportType,
            int tag,
            int project,
            TaskStatus? status,
            Guid departament,
            Guid userId,
            ReportTimeInterval reportTimeInterval,
            ApiDateTime fromDate,
            ApiDateTime toDate,
            int viewType,
            bool noResponsible)
        {
            ProjectSecurity.DemandAuthentication();

            var filter = new TaskFilter
                {
                    TagId = tag,
                    DepartmentId = departament,
                    UserId = userId,
                    TimeInterval = reportTimeInterval,
                    FromDate = fromDate,
                    ToDate = toDate,
                    ViewType = viewType,
                    NoResponsible = noResponsible
                };

            if (project != 0)
            {
                filter.ProjectIds.Add(project);
            }

            if (status != null)
            {
                filter.TaskStatuses.Add((TaskStatus)status);
            }

            var template = EngineFactory.ReportEngine.GetTemplate(reportid);
            template.Filter = filter;

            SaveOrUpdateTemplate(template, name, period, periodItem, hour, autoGenerated);
            MessageService.Send(Request, MessageAction.ReportTemplateUpdated, MessageTarget.Create(template.Id), template.Name);

            return new ReportTemplateWrapper(template);
        }

        ///<summary>
        ///
        ///</summary>
        ///<category>Report</category>
        ///<param name="reportid"></param>
        ///<returns></returns>
        [Read(@"report/{reportid:[0-9]+}")]
        public ReportTemplateWrapper GetReportTemplate(int reportid)
        {
            ProjectSecurity.DemandAuthentication();
            return new ReportTemplateWrapper(EngineFactory.ReportEngine.GetTemplate(reportid).NotFoundIfNull());
        }

        ///<summary>
        ///Deletes the project report template with the ID specified in the request
        ///</summary>
        ///<short>
        ///Delete report template
        ///</short>
        ///<category>Report</category>   
        ///<param name="reportid">Report template ID</param>        
        ///<returns>Project report template</returns>
        [Delete(@"report/{reportid:[0-9]+}")]
        public ReportTemplateWrapper DeleteReportTemplate(int reportid)
        {
            ProjectSecurity.DemandAuthentication();

            var reportEngine = EngineFactory.ReportEngine;

            var reportTemplate = reportEngine.GetTemplate(reportid).NotFoundIfNull();

            reportEngine.DeleteTemplate(reportid);
            MessageService.Send(Request, MessageAction.ReportTemplateDeleted, MessageTarget.Create(reportTemplate.Id), reportTemplate.Name);

            return new ReportTemplateWrapper(reportTemplate);
        }

        [Read(@"report/files")]
        public IEnumerable<FileWrapper> GetGeneratedReports()
        {
            ChechDocBuilder();

            var fileIds = EngineFactory.ReportEngine.Get().Select(r => r.FileId).ToArray();

            return EngineFactory.FileEngine.GetFiles(fileIds).Select(r => new FileWrapper(r)).OrderByDescending(r=> r.Id).ToList();
        }

        [Delete(@"report/files/{fileid:[0-9]+}")]
        public ReportFile RemoveGeneratedReport(int fileid)
        {
            ProjectSecurity.DemandAuthentication();

            var reportEngine = EngineFactory.ReportEngine;

            var report = reportEngine.GetByFileId(fileid).NotFoundIfNull();

            reportEngine.Remove(report);

            return report;
        }

        private void ChechDocBuilder()
        {
            ProjectSecurity.DemandAuthentication();
            if (string.IsNullOrEmpty(FilesLinkUtility.DocServiceDocbuilderUrl))
                throw ProjectSecurity.CreateSecurityException();
        }

        private void SaveOrUpdateTemplate(ReportTemplate template, string title, string period, int periodItem, int hour, bool autoGenerated)
        {
            template.Name = HttpUtility.HtmlEncode(title);
            switch (period)
            {
                case "day":
                    template.Cron = string.Format("0 0 {0} * * ?", hour);
                    break;
                case "week":
                    template.Cron = string.Format("0 0 {0} ? * {1}", hour, periodItem);
                    break;
                case "month":
                    template.Cron = string.Format("0 0 {0} {1} * ?", hour, periodItem);
                    break;
                default:
                    template.Cron = string.Format("0 0 {0} * * ?", 12);
                    break;
            }
            template.AutoGenerated = autoGenerated;
            EngineFactory.ReportEngine.SaveTemplate(template);
        }
    }
}